
package scalaSci

// Vectors are dynamically resizable while double[] arrays are not

 class Vec( n: Int) {
    
    private  var   v = new Array[Double](n);
    private  var  len = n;
    def getv = { v}
    def size = len
    def length = len
 
def this(vals: Array[Double]) = {
    this(vals.length)
    var k=0
    while  (k < vals.length) {
      v(k) = vals(k)
      k += 1
    }
}

  // apply the function f to all the elements of the vector and return the results with a new vector
 def  map( f: (Double => Double)): Vec = {
   var vres = new Vec(len)
    for (k<-0 until len)
     vres(k) = f(v(k))
   vres
 }

  
  def zeros() =  {
    var k=0
    while  (k < len) {
      v(k) = 0.0
      k += 1
    }
}

def apply(k: Int): Double = {
  v(k)
 }

    // APPEND OR PREPEND SCALAR AT VECTOR
    // append element as last vector's element,  e.g. var v = vrand(2); var vv = 4.55 ::  v   // 4.55 is placed as the last element of the vector
def ::(elem: Double): Vec = {
 var v2 = new Array[Double](len+1)
   // def copy (src : AnyRef, srcPos : Int, dest : AnyRef, destPos : Int, length : Int) : Unit
 Array.copy (v, 0, v2, 0, len)
 v2(len) = elem
 len += 1
 v = v2
 this
}

// prepend element as first vector's element, e.g.  var v = vrand(2); var vv = 4.55 :::  v   // 4.55 is placed at the front of the vector
def :::(elem: Double): Vec = {
 var v2 = new Array[Double](len+1)
 v2(0) = elem
 Array.copy (v, 0, v2, 1, len)
 len += 1
 v = v2
 this
}

    // append element as last vector's element,  e.g.  var v = vrand(2); var vv =  v ::<  4.55 // 4.55 is placed as the last element of the vector
def ::<(elem: Double): Vec = {
 var v2 = new Array[Double](len+1)
 Array.copy (v, 0, v2, 0, len)
 v2(len) = elem
 len += 1
 v = v2
 this
}

// prepend element as first vector's element,  e.g.  var v = vrand(2); var vv =  v :::< 4.55   // 4.55 is placed at the front of the vector
def :::<(elem: Double): Vec = {
 var v2 = new Array[Double](len+1)
 v2(0) = elem
 Array.copy (v, 0, v2, 1, len)
 len += 1
 v = v2
 this
}



    // APPEND OR PREPEND VECTOR AT VECTOR

// append left-side vector to right-side vector, e.g.  vones(2) :: vrand(3)
//  res0: scalaSci.Vec =  0.597  0.122  0.045  1.000  1.000
def ::(v2: Vec): Vec = {
    var len2 = v2.len
    var lenAll = len+len2
    var vall = new Array[Double](lenAll)
    Array.copy(v,  0, vall, 0, len)  // copy first array
    var secIdx=0 // copy second array
    for (k<-len to lenAll-1)  { vall(k) = v2(secIdx); secIdx+=1 }
    v = vall
    len = lenAll
 this
}
 
// prepend left-side vector to right-side vector, e.g.  vones(2) ::: vrand(3)
// res1: scalaSci.Vec = 1.000  1.000  0.212  0.633  0.130
def :::(v2: Vec): Vec = {
    var len2 = v2.len
    var lenAll = len+len2
    var vall = new Array[Double](lenAll)
    Array.copy(v2.v,  0, vall, 0, len2)  // copy second array
    var secIdx=0
    for (k<-len2 to lenAll-1)  { vall(k) = v(secIdx); secIdx+=1 }
    v = vall
    len = lenAll
 this
}


// extracts a subvector, v(low:high)
  def apply(low: Int,  high: Int): Vec = {
    var subs = high-low+1;
    var num = Math.abs(subs) 
    var subVec = new Vec(num)   // create a Vector to keep the extracted range
      // fill the created vector with values
    var celem = low  // indexes current element
    var idx = 0  // indexes at the new Vector
    var inc = 1; if (low > high) inc = -1
    if (inc > 0) {
        while  ( celem <= high )   {
          subVec.v(idx) = v(celem)
          idx += 1
          celem += inc
          } 
 }
else {
 while  ( celem >= high )   {
          subVec.v(idx) = v(celem)
          idx += 1
          celem += inc
          }
      }
     subVec
}

    
// extracts a subvector, v(low:inc:high)
  def apply(low: Int,  inc: Int, high: Int): Vec = {
    
    var num = Math.floor( (high-low) / inc).asInstanceOf[Int]+1
    var subVec = new Vec(num)   // create a Vector to keep the extracted range
      // fill the created vector with values
    var celem = low  // indexes current element
    var idx = 0  // indexes at the new Vector
    if (inc > 0) {
        while  ( celem <= high )   {
          subVec.v(idx) = v(celem)
          idx += 1
          celem += inc
          } 
 }
else {
 while  ( celem >= high )   {
          subVec.v(idx) = v(celem)
          idx += 1
          celem += inc
          }
      }
     subVec
 }


  
def  update(k: Int, value: Double): Unit = {
    if (k >= len) {   // increase the size of the vector dynamically
 var newSize  = (Vec.vecResizeFactor*k).asInstanceOf[Int]
 var v2 = new Array[Double](newSize)
 Array.copy (v, 0, v2, 0, len) 
 v = v2
 len = newSize
  }

 v(k) = value;
 }

    // update a Vector subrange by assigning a Vector
 def update(lowp:Int, incp: Int, highp: Int, vr: Vec): Unit = {
     var low=lowp; var high=highp; var inc = incp;
     if (high < low)  {
            if (inc > 0)  {
                println("negative subrange increment is required")
                this
            }
            var tmp=highp; var high=lowp; low = tmp;
            inc  = -inc
        }

      var vl_rhs = vr.len   // length of right-hand side vector
     var rangeLen = ((high-low)/inc).asInstanceOf[Int]+1    // length of target range
     if (vl_rhs != rangeLen)  {  // improper sizes of the involved vector subranges for assignment
         println("target vector subrange and right-hand size vector lengths do not agree, i.e. v1_rhs =  "+vl_rhs+", rangeLen = "+rangeLen)
         this   // return the vector unaltered
     }

      if (high >= len)  {   // dynamically increase the size of the Vector
 var newSize  = (Vec.vecResizeFactor*high).asInstanceOf[Int]
 var v2 = new Array[Double](newSize)
 Array.copy (v, 0, v2, 0, len)
 v = v2
 len = newSize
     }

     // copy the values of the vr
        var k=0; var lidx=low
        while (k < vr.len) {
            v(lidx) = vr(k)
            k += 1
            lidx += inc 
        }
  }
 
    // update a Vector subrange by assigning a Vector
 def update(lowp:Int,  highp: Int, vr: Vec): Unit = {
     var low=lowp; var high=highp; var inc = 1;
     if (high < low)  {
            if (inc > 0)  {
                println("negative subrange increment is required")
                this
            }
            var tmp=highp; var high=lowp; low = tmp;
        }

      var vl_rhs = vr.len   // length of right-hand side vector
     var rangeLen = ((high-low)/inc).asInstanceOf[Int]+1    // length of target range
     if (vl_rhs != rangeLen)  {  // improper sizes of the involved vector subranges for assignment
         println("target vector subrange and right-hand size vector lengths do not agree, i.e. v1_rhs =  "+vl_rhs+", rangeLen = "+rangeLen)
         this   // return the vector unaltered
     }

      if (high >= len)  {   // dynamically increase the size of the Vector
 var newSize  = (Vec.vecResizeFactor*high).asInstanceOf[Int]
 var v2 = new Array[Double](newSize)
 Array.copy (v, 0, v2, 0, len)
 v = v2
 len = newSize
     }

     // copy the values of the vr
        var k=0; var lidx=low
        while (k < vr.len) {
            v(lidx) = vr(k)
            k += 1
            lidx += inc
        }
  }


 def rand() {
    var k=0
    while  (k < len) {
      v(k) = java.lang.Math.random
      k += 1
    }
}

// unary Minus applied to a Vector implies negation of all of its elements
def unary_- : Vec =  {
      var nv = new Vec(this.len)  // construct a Vector of the same dimension
   var i=0; 
   while (i<this.len) {
      nv.v(i) = -v(i)  // negate element
      i += 1
    }
    nv
}    
   // perform an addition of the Vector specified as a parameter to this
   // if the Vectors are not of the same size:
   //   if the receiver's length is 1 expand the receiver filling with the value of the 0th element (since implicit conversion is assumed)
def + (that: Vec): Vec =  {
    var nR = this.len // receiver's length
    var nThat = that.len   // right argument length
    var maxLen = nThat;
    if (nR > maxLen)  maxLen = nR;

    var nv = new Vec(maxLen)  // create a new Vector equal to the maximum sized Vector
    if (nR == 1 && nR<maxLen)  {  // implicit conversion
        var value = this.v(0)  // get the value to copy to the coverted array
        var k=0
        while (k < maxLen) {
          nv(k)=value+that.v(k)
          k += 1
        }
         nv
      }
    else  {
        if (nR > nThat) {   // receiver's Vector largest
       var i=0
       while (i < nThat)  {
          nv(i) = v(i)+that.v(i)
          i += 1
       }
       i = nThat
       while (i < nR) {
         nv(i) = v(i)
         i += 1
        }
        nv
    }
    else  {   // parameter's Vector largest
        var i = 0
        while (i < nR) {
         nv(i) = v(i)+that.v(i)
         i += 1
        }
        i = nR
        while (i < nThat) {
         nv(i) = that.v(i)
         i += 1
        }
      nv
       }
    }
}

// IN-PLACE Operations: Update directly the receiver, avoiding creating a new return object

def ++ (that: Vec): Vec =  {
    var nR = this.len // receiver's length
    var nThat = that.len   // right argument length
    var minLen = nThat;
    if (nR < minLen)  minLen = nR;
 // perform the addition
    var k=0
    while (k<minLen)  {
        this.v(k) += that.v(k)
        k+=1
    }
    this
}

def ++ (that: Double): Vec =  {
    var nR = this.len // receiver's length
    // perform the addition
    var k=0
    while (k<nR)  {
        this.v(k) += that
        k+=1
    }
    this
}

def ++ (that: Int): Vec =  {
    var nR = this.len // receiver's length
    // perform the addition
    var k=0
    while (k<nR)  {
        this.v(k) += that
        k+=1
    }
    this
}

def ++ (that: Long): Vec =  {
    var nR = this.len // receiver's length
    // perform the addition
    var k=0
    while (k<nR)  {
        this.v(k) += that
        k+=1
    }
    this
}

def -- (that: Vec): Vec =  {
    var nR = this.len // receiver's length
    var nThat = that.len   // right argument length
    var minLen = nThat;
    if (nR < minLen)  minLen = nR;
 // perform the addition
    var k=0
    while (k<minLen)  {
        this.v(k) -= that.v(k)
        k+=1
    }
    this
}

def -- (that: Double): Vec =  {
    var nR = this.len // receiver's length
    // perform the addition
    var k=0
    while (k<nR)  {
        this.v(k) -= that
        k+=1
    }
    this
}

def -- (that: Int): Vec =  {
    var nR = this.len // receiver's length
    // perform the addition
    var k=0
    while (k<nR)  {
        this.v(k) -= that
        k+=1
    }
    this
}

def -- (that: Long): Vec =  {
    var nR = this.len // receiver's length
    // perform the addition
    var k=0
    while (k<nR)  {
        this.v(k) -= that
        k+=1
    }
    this
}

def ** (that: Double): Vec =  {
    var nR = this.len // receiver's length
    // perform the addition
    var k=0
    while (k<nR)  {
        this.v(k) *= that
        k+=1
    }
    this
}

def ** (that: Int): Vec =  {
    var nR = this.len // receiver's length
    // perform the addition
    var k=0
    while (k<nR)  {
        this.v(k) *= that
        k+=1
    }
    this
}

def ** (that: Long): Vec =  {
    var nR = this.len // receiver's length
    // perform the addition
    var k=0
    while (k<nR)  {
        this.v(k) *= that
        k+=1
    }
    this
}


 def \/ (that: Double): Vec =  {
    var nR = this.len // receiver's length
    // perform the addition
    var k=0
    while (k<nR)  {
        this.v(k) /= that
        k+=1
    }
    this
}

// any method that ends in a ':' character is invoked on its right operand, passing in the left operand
// we define some operators that help to avoid implicit conversions for even better code efficiency

def +: (that: Double): Vec =  {
   var N=this.len
   var k=0
   while (k<N) {
       this.v(k) += that
       k+=1
   }
        this 
}

def +: (that: Int): Vec =  {
  var N=this.len
   var k=0
   while (k<N) {
       this.v(k) += that
       k+=1
   }
        this
}

def +: (that: Long): Vec =  {
   var N=this.len
   var k=0
   while (k<N) {
       this.v(k) += that
       k+=1
   }
        this
}

def -: (that: Double): Vec =  {
   var N=this.len
   var k=0
   while (k<N) {
       this.v(k) = that-this.v(k)
       k+=1
   }
    this
}

def -: (that: Int): Vec =  {
   var N=this.len
   var k=0
   while (k<N) {
       this.v(k) = that-this.v(k)
       k+=1
   }
    this
}

def -: (that: Long): Vec =  {
   var N=this.len
   var k=0
   while (k<N) {
       this.v(k) = that-this.v(k)
       k+=1
   }
    this
}


def *: (that: Double): Vec =  {
   var N=this.len
   var k=0
   while (k<N) {
       this.v(k) = that*this.v(k)
       k+=1
   }
    this
}

def *: (that: Int): Vec =  {
   var N=this.len
  println("int multiplying Vec, dim = "+N)
   var k=0
   while (k<N) {
       this.v(k) = that*this.v(k)
       k+=1
   }
    this
}

def *: (that: Long): Vec =  {
   var N=this.len
   var k=0
   while (k<N) {
       this.v(k) = that*this.v(k)
       k+=1
   }
    this
}


def /: (that: Double): Vec =  {
   var N=this.len
   var k=0
   while (k<N) {
       this.v(k) = that/this.v(k)
       k+=1
   }
    this
}


def / (that: Double): Vec =  {
   var nv = new Vec(len)
   var k=0
   while (k<len) {
       nv.v(k) = this.v(k)/that
       k+=1
   }
    nv
}



def / (that: Array[Double]): Vec =  {
   var nR = this.len // receiver's length
    var nThat = that.length   // right argument length
    var maxLen = nThat;
    if (nR > maxLen)  maxLen = nR;

    var nv = new Vec(maxLen)  // create a new Vector equal to the maximum sized Vector
    if (nR == 1 && nR<maxLen)  {  // implicit conversion
        var value = this.v(0)  // get the value to copy to the coverted array
        var k=0
        while (k < maxLen) {
          nv(k)=value / that(k)
          k += 1
        }
         nv
      }
    else  {
        if (nR > nThat) {   // receiver's Vector largest
       var i=0
       while (i < nThat)  {
          nv(i) = v(i) / that(i)
          i += 1
       }
       i = nThat
       while (i < nR) {
         nv(i) = v(i)
         i += 1
        }
        nv
    }
    else  {   // parameter's Vector largest
        var i = 0
        while (i < nR) {
         nv(i) = v(i) / that(i)
         i += 1
        }
        i = nR
        while (i < nThat) {
         nv(i) = that(i)
         i += 1
        }
      nv
       }
    }
}


def / (that: Vec): Vec =  {
    var nR = this.len // receiver's length
    var nThat = that.length   // right argument length
    var maxLen = nThat;
    if (nR > maxLen)  maxLen = nR;

    var nv = new Vec(maxLen)  // create a new Vector equal to the maximum sized Vector
    if (nR == 1 && nR<maxLen)  {  // implicit conversion
        var value = this.v(0)  // get the value to copy to the coverted array
        var k=0
        while (k < maxLen) {
          nv(k)=value / that(k)
          k += 1
        }
         nv
      }
    else  {
        if (nR > nThat) {   // receiver's Vector largest
       var i=0
       while (i < nThat)  {
          nv(i) = v(i) / that(i)
          i += 1
       }
       i = nThat
       while (i < nR) {
         nv(i) = v(i)
         i += 1
        }
        nv
    }
    else  {   // parameter's Vector largest
        var i = 0
        while (i < nR) {
         nv(i) = v(i) / that(i)
         i += 1
        }
        i = nR
        while (i < nThat) {
         nv(i) = that(i)
         i += 1
        }
      nv
       }
    }
}


// perform an addition of the Vector specified as a parameter to this
   // if the Vectors are not of the same size:
   //   if the receiver's length is 1 expand the receiver filling with the value of the 0th element (since implicit conversion is assumed)
def + (that: Array[Double]): Vec =  {
    var nR = this.len // receiver's length
    var nThat = that.length   // right argument length
    var maxLen = nThat;
    if (nR > maxLen)  maxLen = nR;

    var nv = new Vec(maxLen)  // create a new Vector equal to the maximum sized Vector
    if (nR == 1 && nR<maxLen)  {  // implicit conversion
        var value = this.v(0)  // get the value to copy to the coverted array
        var k=0
        while (k < maxLen) {
          nv(k)=value+that(k)
          k += 1
        }
         nv
      }
    else  {
        if (nR > nThat) {   // receiver's Vector largest
       var i=0
       while (i < nThat)  {
          nv(i) = v(i)+that(i)
          i += 1
       }
       i = nThat
       while (i < nR) {
         nv(i) = v(i)
         i += 1
        }
        nv
    }
    else  {   // parameter's Vector largest
        var i = 0
        while (i < nR) {
         nv(i) = v(i)+that(i)
         i += 1
        }
        i = nR
        while (i < nThat) {
         nv(i) = that(i)
         i += 1
        }
      nv
       }
    }
}


// perform a subtraction of the Vector specified as a parameter to this
   // if the Vectors are not of the same size:
   //   if the receiver's length is 1 expand the receiver filling with the value of the 0th element (since implicit conversion is assumed)
def - (that: Vec): Vec =  {
var nR = this.len // receiver's length
    var nThat = that.len   // right argument length
    var maxLen = nThat;
    if (nR > maxLen)  maxLen = nR;

    var nv = new Vec(maxLen)  // create a new Vector equal to the maximum sized Vector
    if (nR == 1 && nR<maxLen)  {  // implicit conversion
        var value = this.v(0)  // get the value to copy to the coverted array
        var k=0
        while (k < maxLen) {
          nv(k)=value-that.v(k)
          k += 1
        }
         nv
      }
    else  {
        if (nR > nThat) {   // receiver's Vector largest
       var i=0
       while (i < nThat)  {
          nv(i) = v(i)+that.v(i)
          i += 1
       }
       i = nThat
       while (i < nR) {
         nv(i) = v(i)
         i += 1
        }
        nv
    }
    else  {   // parameter's Vector largest
        var i = 0
        while (i < nR) {
         nv(i) = v(i)-that.v(i)
         i += 1
        }
        i = nR
        while (i < nThat) {
         nv(i) = that.v(i)
         i += 1
        }
      nv
       }
    }
}


// perform a multiplication  of the Vector specified as a parameter to this
   // if the Vectors are not of the same size:
   //   if the receiver's length is 1 expand the receiver filling with the value of the 0th element (since implicit conversion is assumed)
def * (that: Vec): Vec =  {
    var nR = this.len // receiver's length
    var nThat = that.len   // right argument length
    var maxLen = nThat;

  if (nR > maxLen)  maxLen = nR;

    var nv = new Vec(maxLen)  // create a new Vector equal to the maximum sized Vector
    if (nR == 1 && nR<maxLen)  {  // implicit conversion
        var value = this.v(0)  // get the value to copy to the coverted array
        var k=0
        while (k < maxLen) {
          nv(k)=value*that.v(k)
          k += 1
        }
         nv
      }
    else  {
        if (nR > nThat) {   // receiver's Vector largest
       var i=0
       while (i < nThat)  {
          nv(i) = v(i)*that.v(i)
          i += 1
       }
       i = nThat
       while (i < nR) {
         nv(i) = v(i)
         i += 1
        }
        nv
    }
    else  {   // parameter's Vector largest
        var i = 0
        while (i < nR) {
         nv(i) = v(i)*that.v(i)
         i += 1
        }
        i = nR
        while (i < nThat) {
         nv(i) = that.v(i)
         i += 1
        }
      nv
       }
    }
}

// implements dot product for vectors
def  dot (that: Vec): Vec = {
    return  this * that   // treat dot product as multiplication
}

def + (that: Double): Vec =  {
      var nv = new Vec(len)
      var i=0
      while  (i< len) {
        nv(i) = v(i)+that
        i += 1
      }
   nv
}

// Vec - Array[Double]
 def - (that: Array[Double]): Vec =  {
   var  rN = this.len
   var  sN = that.length


  if (rN == 1 && sN > rN )  {  //  an implicit conversion is implied when the receiver
       var nv = new Vec(sN)                     // is a 1 X 1 matrix and the parameter is a larger one
       var value = this.v(0)
   var i=0
   while (i<sN) {
       nv.v(i) = value - that(i)
       i+=1
     }
     return nv
    }  // implicit conversion

   else if (rN == sN)  {     // same dimensions
       var nv = new Vec(sN)
       var i=0
   while (i<sN)  {
        nv.v(i) = v(i) - that(i)
        i += 1
   }
   return nv
  }
  else { // incompatible dimensions
   this
     }
}

 
def -: (that: Array[Double]): Vec =  {
   this - that
}

 def - (that: Double): Vec =  {
    var nv = new Vec(len)
    var i=0
      while  (i< len) {
       nv(i) = v(i)-that
       i += 1
      }
   nv
}

 def * (that: Double): Vec =  {
    var len = this.len
    var nv = new Vec(len)
    var i=0
    while  (i< len) {
       nv(i) = v(i)*that
       i += 1
      }
   nv
}

def * (that: Int): Vec =  {
    var len = this.len
    var nv = new Vec(len)
      var i=0
    while  (i< len) {
       nv(i) = v(i)*that
       i += 1
      }
   nv
}

    // Vector * Double[Array]
 def * (that: Array[Double]): Vec =  {
    var thatLen = that.length
   //  the case scalar *Array[Double] is handled by implicitly converted the scalar to Vector 
    if (len == 1)  { // perhaps  implicit conversion from double to Vec has performed
     var dv = v(0)
     var nv = new Vec(thatLen)
     var i=0
    while  (i< thatLen) {
       nv(i) = dv*that(i)
       i += 1
      }
   return nv
        }
    // handle Vector * Array[Double] like a dot-product
    var resLen = len
    if (thatLen < len)
      resLen = thatLen
    var nv = new Vec(resLen)
    var i=0
    while  (i< resLen) {
       nv(i) = v(i)*that(i)
       i += 1
      }
   return nv
}

def  print = {
  var digitFormat = scalaExec.Interpreter.GlobalValues.fmtMatrix
    var nelems = len

     var elemsPerLine = 30
     var i=1
     var lineElems = 0
    while (i<nelems) {
        var str = digitFormat.format(v(i)) +"  "
        Console.print(str)
        lineElems += 1
        if (lineElems==elemsPerLine) {
          lineElems=0
          println
         }
       i+=1
        }
 }


override  def  toString(): String = {
     var digitFormat = scalaExec.Interpreter.GlobalValues.fmtMatrix
     var s  ="\n"
     var mxElems = len
     var moreElems = ""
     if (mxElems > Vec.mxElemsToDisplay )  {
         mxElems = Vec.mxElemsToDisplay
         moreElems = " .... "
     }
     var i=0
     while (i < mxElems) {
        s = s+digitFormat.format(v(i))+"  "
        i += 1
       }
     s=s+moreElems+"\n"
     s

 }

}

object Vec  {

  
    var mxElemsToDisplay = 20    // controls maximum number of Vector elements to display
    def setMxElemsToDisplay( mxElems: Int): Int  = { var prevElems = mxElemsToDisplay; mxElemsToDisplay = mxElems; prevElems}
    var vecResizeFactor = 1.5   // controls by how much to increase dynamically the size of the vector }
    def setVecResizeFactor( newResizeFactor: Double):Double = { var prevResizeFactor = vecResizeFactor;  vecResizeFactor = newResizeFactor; prevResizeFactor }
       
    
// construct a Vec from a String , e,g,
// var m = V("3.4 -6.7 -1.2 5.6")
def  V(s: String) =  {
    
// count how many numbers the String s has. Assuming that each line has the same number of elements
var nelems = 0 
var strtok = new java.util.StringTokenizer(s, ", ")  // elements are separated by ',' or ' '
 while (strtok.hasMoreTokens) {
   val tok = strtok.nextToken
   nelems += 1  
}

// allocate double array
var elems = new Array[Double](nelems)
strtok = new java.util.StringTokenizer(s, ", ")  // elements are separated by ',' or ' '
var k=0
 while (strtok.hasMoreTokens) {
   val tok = strtok.nextToken
   elems(k) = tok.toDouble
   k += 1  
}

 // return the converted Matrix
 new Vec(elems)
 }  

    // implicit conversion from Double[Array] to Vec
   def toVector(da: Array[Double]): Vec = {
       new Vec(da)
   }

    def vones(n: Int): Vec = {
         var v = new Vec(n)
         var i=0;   while (i<n) {    v(i) = 1.0; i += 1; }
          v
    }


 def  vzeros(n: Int): Vec = {
      var v = new Vec(n)
      var i=0;  while (i < n) {  v(i) = 0.0; i += 1; }
      v
  }

def min(v: Vec): Double = {
  var l = v.length
  var mn = v(0)
  for (k<-1 to l-1)
   if (v(k) < mn) mn = v(k)
mn
}

def max(v: Vec): Double = {
  var l = v.length
  var mx = v(0)
  for (k<-1 to l-1)
   if (v(k) > mx) mx = v(k)
mx
}


 def vfill(n: Int, value: Double): Vec = {
      var v = new Vec(n)
      var i=0;  while (i < n) {  v(i) = value; i += 1; }
      v
  }

def vfill(n: Int, value: Int): Vec = {
      var v = new Vec(n)
      var i=0;  while (i < n) {  v(i) = value; i += 1; }
      v
  }

def vfill(n: Int, value: Short): Vec = {
      var v = new Vec(n)
      var i=0;  while (i < n) {  v(i) = value; i += 1; }
      v
  }

def vfill(n: Int, value: Long): Vec = {
      var v = new Vec(n)
      var i=0;  while (i < n) {  v(i) = value; i += 1; }
      v
  }

def linspace(startv: Double, endv: Double): Vec = {
    var nP = 100  // use 100 as default number of points
    var v = new Vec(nP)
    var dx = (startv-endv)/(nP-1)
    for (i<-0 until nP)
	v(i) = startv +  i * dx

 v
}

def linspace(startv: Double, endv: Double, nP: Int): Vec = {
    var v = new Vec(nP)
    var dx = (startv-endv)/(nP-1)
    for (i<-0 until nP)
	v(i) = startv +  i * dx

 v
}

// use by default logspace=10
def logspace(startOrig: Double, endOrig: Double, nP: Int): Vec = {
    logspace(startOrig, endOrig, nP, 10.0)
}

def logspace(startOrig: Double, endOrig: Double, nP: Int, logBase: Double): Vec = {
    var  positiveTransformed = false
    var  transformToPositive=0.0
                
    var  start = startOrig; var  end=endOrig  // use these values to handle negative values
    var  axisReversed = false
    if (start > end)   {   // reverse axis
            start = endOrig; end = startOrig; axisReversed = true;
        }
                
     if (start <= 0)  {  // make values positive
             transformToPositive = -start+1;  start = 1;     
             end = end+transformToPositive;  positiveTransformed = true;
        }
     var   logBaseFactor = 1/java.lang.Math.log10(logBase)
     var   start_tmp = java.lang.Math.log10(start)*logBaseFactor
     var   end_tmp = java.lang.Math.log10(end)*logBaseFactor
     //println("logBaseFactor = "+logBaseFactor+"  start_tmp = "+start_tmp+"  end_tmp = "+end_tmp)
                
    var   values = new Vec(nP)
    var  dx     = (end_tmp-start_tmp) / (nP-1)
    for (i <- 0 until nP)
        values(i) = java.lang.Math.pow( logBase, (start_tmp +  i * dx)) 
		
        if  (positiveTransformed)    // return to the original range of values
                {
              for ( i <- 0 until nP )
		  values( i) = values(i)-transformToPositive
		  start = start-transformToPositive
                }

                if (axisReversed)  {
                    var valuesNew = new Vec(nP);
                    valuesNew(0) = values(nP-1)
                    for ( i<-1 until nP)  {
                        valuesNew(i) = valuesNew( i-1)-(values(i)-values(i-1))
                    }
                    valuesNew
                }
                          
     values
}


		

 def inc(begin: Double, pitch: Double,  end: Double): Vec = {
     var siz = ((end - begin) / pitch).asInstanceOf[Int]+1
     var doubleArr = new Array[Double](siz)
     var i=0;  while (i < siz) {   doubleArr(i) = begin + i * pitch;  i += 1;  }
   new Vec(doubleArr)
	}


def sin(v: Vec): Vec = {
       var N = v.len;
       var ov = new Vec(N)
       var i=0
       while  (i< N) {
            ov.v(i) =  java.lang.Math.sin(v.v(i))
            i += 1
            }
          ov
    }

    def cos(v: Vec): Vec = {
       var N = v.len;
       var ov = new Vec(N)
       var i=0
       while  (i< N) {
            ov.v(i) =  java.lang.Math.cos(v.v(i))
            i += 1
            }
          ov
    }

def tan(v: Vec): Vec = {
       var N = v.len;
       var ov = new Vec(N)
       var i=0
       while  (i< N) {
            ov.v(i) =  java.lang.Math.tan(v.v(i))
            i += 1
            }
          ov
    }

    def asin(v: Vec): Vec = {
       var N = v.len;
       var ov = new Vec(N)
       var i=0
       while  (i< N) {
            ov.v(i) =  java.lang.Math.asin(v.v(i))
            i += 1
            }
          ov
    }

def acos(v: Vec): Vec = {
       var N = v.len;
       var ov = new Vec(N)
       var i=0
       while  (i< N) {
            ov.v(i) =  java.lang.Math.acos(v.v(i))
            i += 1
            }
          ov
    }

    def atan(v: Vec): Vec = {
       var N = v.len;
       var ov = new Vec(N)
       var i=0
       while  (i< N) {
            ov.v(i) =  java.lang.Math.atan(v.v(i))
            i += 1
            }
          ov
    }

    def sinh(v: Vec): Vec = {
       var N = v.len;
       var ov = new Vec(N)
       var i=0
       while  (i< N) {
            ov.v(i) =  java.lang.Math.sinh(v.v(i))
            i += 1
            }
          ov
    }

    def cosh(v: Vec): Vec = {
       var N = v.len;
       var ov = new Vec(N)
       var i=0
       while  (i< N) {
            ov.v(i) =  java.lang.Math.cosh(v.v(i))
            i += 1
            }
          ov
    }

    def tanh(v: Vec): Vec = {
       var N = v.len;
       var ov = new Vec(N)
       var i=0
       while  (i< N) {
            ov.v(i) =  java.lang.Math.tanh(v.v(i))
            i += 1
            }
          ov
    }

def exp(v: Vec): Vec = {
       var N = v.len;
       var ov = new Vec(N)
       var i=0
       while  (i< N) {
            ov.v(i) =  java.lang.Math.exp(v.v(i))
            i += 1
            }
          ov
    }

    def log(v: Vec): Vec = {
       var N = v.len;
       var ov = new Vec(N)
       var i=0
       while  (i< N) {
            ov.v(i) =  java.lang.Math.log(v.v(i))
            i += 1
            }
          ov
    }

    def log2(v: Vec): Vec = {
       var N = v.len;
       var ov = new Vec(N)
       var conv = java.lang.Math.log(2.0)
       var i=0
       while  (i< N) {
            ov.v(i) =  java.lang.Math.log(v.v(i))/conv
            i += 1
            }
          ov
    }

    def log10(v: Vec): Vec = {
       var N = v.len;
       var ov = new Vec(N)
       var i=0
       while  (i< N) {
            ov.v(i) =  java.lang.Math.log10(v.v(i))
            i += 1
            }
          ov
    }

    def abs(v: Vec): Vec = {
       var N = v.len;
       var ov = new Vec(N)
       var i=0
       while  (i< N) {
            ov.v(i) =  java.lang.Math.abs(v.v(i))
            i += 1
            }
          ov
    }

    def ceil(v: Vec): Vec = {
       var N = v.len;
       var ov = new Vec(N)
       var i=0
       while  (i< N) {
            ov.v(i) =  java.lang.Math.ceil(v.v(i))
            i += 1
            }
          ov
    }

    def floor(v: Vec): Vec = {
       var N = v.len;
       var ov = new Vec(N)
       var i=0
       while  (i< N) {
            ov.v(i) =  java.lang.Math.floor(v.v(i))
            i += 1
            }
          ov
    }

    def round(v: Vec): Vec = {
       var N = v.len;
       var ov = new Vec(N)
       var i=0
       while  (i< N) {
            ov.v(i) =  java.lang.Math.round(v.v(i))
            i += 1
            }
          ov
    }

  def sqrt(v: Vec): Vec = {
       var N = v.len;
       var ov = new Vec(N)
       var i=0
       while  (i< N) {
            ov.v(i) =  java.lang.Math.sqrt(v.v(i))
            i += 1
            }
          ov
    }

    def toDegrees(v: Vec): Vec = {
       var N = v.len;
       var ov = new Vec(N)
       var i=0
       while  (i< N) {
            ov.v(i) =  java.lang.Math.toDegrees(v.v(i))
            i += 1
            }
          ov
    }

    def toRadians(v: Vec): Vec = {
       var N = v.len;
       var ov = new Vec(N)
       var i=0
       while  (i< N) {
            ov.v(i) =  java.lang.Math.toRadians(v.v(i))
            i += 1
            }
          ov
    }
    
    def pow(v: Vec, exponent:Double): Vec = {
       var N = v.len;
       var ov = new Vec(N)
       var i=0
       while  (i< N) {
            ov.v(i) =  java.lang.Math.pow(v.v(i), exponent)
            i += 1
            }
          ov
    }

def  mean(v: Vec): Double =  {
       var  mn = 0.0
       var  m = v.length
       var i=0
       while  (i < m) {
            mn += v(i)
            i += 1
          }
        mn /=  m;
       mn
    }

def sum(v: Vec): Double = {
    var sm = 0.0
    var m = v.length
    var i=0
    while (i < m) {
        sm += v(i)
        i += 1
    }
    sm
}

def prod(v: Vec): Double = {
    var pd = 1.0
    var m = v.length
    var i=0
    while (i < m) {
        pd *= v(i)
        i += 1
    }
    pd
}


    def rand(N: Int):Vec = {
    var  v = new Array[Double](N);
    var k=0
    while  (k < N) {
      v(k) = java.lang.Math.random
      k += 1
    }
   new Vec(v)

}
}

         

object  matlabColons {

// treat pattern low:inc:high, e.g.  v("3:2:15")
    def unapply (input: String) : Option[(Int, Int, Int)] = {
         try {
             if (input contains ":") {
                 val splitQuote = input split ":"
                 val len = splitQuote.length
                 if (len == 3)   // increment also specified
                    Some(splitQuote(0).toInt, splitQuote(1).toInt, splitQuote(2).toInt)
                 else {
                     val firstLimit = splitQuote(0).toInt
                     val secondLimit = splitQuote(1).toInt
                     var inc = 1
                     if (firstLimit > secondLimit)
                        inc  = -1
                    Some(firstLimit, inc, secondLimit)
             } 
  }
          
             else {
                 None
             }
         }
         catch {
             case _ : NumberFormatException => None
         }
     }

    

def sin(vin: Vec): Vec = {
      var  n = vin.length-1
      var  v = new Vec(n+1)
      var i=0;  while (i < n) {    v(i) =  java.lang.Math.sin(vin(i)); i += 1;  }
      v
  }

 def cos(vin: Vec): Vec = {
      var  n = vin.length-1
      var  v = new Vec(n+1)
      var i=0;  while (i < n) {    v(i) =  java.lang.Math.cos(vin(i)); i += 1;  }
      v
  }

 def tan(vin: Vec): Vec = {
      var  n = vin.length-1
      var  v = new Vec(n+1)
      var i=0;  while (i < n) {    v(i) =  java.lang.Math.tan(vin(i)); i += 1;  }
      v
  }

 def asin(vin: Vec): Vec = {
      var  n = vin.length-1
      var  v = new Vec(n+1)
      var i=0;  while (i < n) {    v(i) =  java.lang.Math.asin(vin(i)); i += 1;  }
      v
  }

 def acos(vin: Vec): Vec = {
      var  n = vin.length-1
      var  v = new Vec(n+1)
      var i=0;  while (i < n) {    v(i) =  java.lang.Math.acos(vin(i)); i += 1;  }
        v
  }

  def atan(vin: Vec): Vec = {
      var  n = vin.length-1
      var  v = new Vec(n+1)
      var i=0;  while (i < n) {    v(i) =  java.lang.Math.atan(vin(i)); i += 1;  }
      v
  }

     def sinh(vin: Vec): Vec = {
      var  n = vin.length-1
      var  v = new Vec(n+1)
      var i=0;  while (i < n) {    v(i) =  java.lang.Math.sinh(vin(i)); i += 1;  }
      v
  }

     def cosh(vin: Vec): Vec = {
      var  n = vin.length-1
      var  v = new Vec(n+1)
      var i=0;  while (i < n) {    v(i) =  java.lang.Math.cosh(vin(i)); i += 1;  }
      v
  }

    def tanh(vin: Vec): Vec = {
      var  n = vin.length-1
      var  v = new Vec(n+1)
      var i=0;  while (i < n) {    v(i) =  java.lang.Math.tanh(vin(i)); i += 1;  }
      v
  }


     def exp(vin: Vec): Vec = {
      var  n = vin.length-1
      var  v = new Vec(n+1)
      var i=0;  while (i < n) {    v(i) =  java.lang.Math.exp(vin(i)); i += 1;  }
      v
  }


 def log(vin: Vec): Vec = {
      var  n = vin.length-1
      var  v = new Vec(n+1)
      var i=0;  while (i < n) {    v(i) =  java.lang.Math.log(vin(i)); i += 1;  }
      v
  }

     def log2(vin: Vec): Vec = {
      var conv = java.lang.Math.log(2.0)
      var  n = vin.length-1
      var  v = new Vec(n+1)
      var i=0;  while (i < n) {    v(i) =  java.lang.Math.log(vin(i))/conv; i += 1;  }
      v
  }

     def log10(vin: Vec): Vec = {
      var  n = vin.length-1
      var  v = new Vec(n+1)
      var i=0;  while (i < n) {    v(i) =  java.lang.Math.log10(vin(i)); i += 1;  }
      v
  }

     def abs(vin: Vec): Vec = {
      var  n = vin.length-1
      var  v = new Vec(n+1)
      var i=0;  while (i < n) {    v(i) =  java.lang.Math.abs(vin(i)); i += 1;  }
      v
  }

 def ceil(vin: Vec): Vec = {
      var  n = vin.length-1
      var  v = new Vec(n+1)
      var i=0;  while (i < n) {    v(i) =  java.lang.Math.ceil(vin(i)); i += 1;  }
      v
  }

 def floor(vin: Vec): Vec = {
      var  n = vin.length-1
      var  v = new Vec(n+1)
      var i=0;  while (i < n) {    v(i) =  java.lang.Math.floor(vin(i)); i += 1;  }
      v
  }

  def round(vin: Vec): Vec = {
      var  n = vin.length-1
      var  v = new Vec(n+1)
      var i=0;  while (i < n) {    v(i) =  java.lang.Math.round(vin(i)); i += 1;  }
      v
  }

 def sqrt(vin: Vec): Vec = {
      var  n = vin.length-1
      var  v = new Vec(n+1)
      var i=0;  while (i < n) {    v(i) =  java.lang.Math.sqrt(vin(i)); i += 1;  }
      v
  }

 def toDegrees(vin: Vec): Vec = {
      var  n = vin.length-1
      var  v = new Vec(n+1)
      var i=0;  while (i < n) {    v(i) =  java.lang.Math.toDegrees(vin(i)); i += 1;  }
      v
  }

 def toRadians(vin: Vec): Vec = {
      var  n = vin.length-1
      var  v = new Vec(n+1)
      var i=0;  while (i < n) {    v(i) =  java.lang.Math.toRadians(vin(i)); i += 1;  }
      v
  }

  def pow(vin: Vec, exponent: Double): Vec = {
      var  n = vin.length-1
      var  v = new Vec(n+1)
      var i=0;  while (i < n) {    v(i) =  java.lang.Math.pow(vin(i), exponent); i += 1;  }
      v
  }

  
  
}

